home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 January: Mac OS SDK / Dev.CD Jan 96 SDK / Dev.CD Jan 96 SDK1.toast / Development Kits (Disc 1) / AOCE / Development Tools / Sample Code / Digital Signatures / SIGSimpleTest Beta / SIGSimpleTest.c < prev    next >
Encoding:
Text File  |  1993-02-22  |  14.5 KB  |  541 lines  |  [TEXT/KAHL]

  1. /*
  2.     File:        SIGSimpleTest.c
  3.  
  4.     Contains:    Sample source from Digital Signature chapter of Inside Mac
  5.  
  6.     Copyright:    © 1993 by Apple Computer, Inc., all rights reserved.
  7.  
  8.     Notes:        This code implements the sample source from Inside Mac.
  9.                 However, there are a few places where a small addition or
  10.                 adjustment was necessary to accomodate this sample. The
  11.                 changes simply have to do with displaying information in 
  12.                 the console window for the DisplayCertificateSet function.
  13.                 
  14.                 What this sample does:
  15.                 • This sample first performs a signing operation on a simple 
  16.                 buffer.  The signature is stored in a global for convenience
  17.                 only, you will want to associate it with a document and 
  18.                 most likely a specific part of a document.  
  19.                 
  20.                 • The signature is then verified, and the SIGShowSigner dialog 
  21.                 is presented.
  22.                 
  23.                 • Finally, the certificate set is output to the console.
  24.                 
  25.                 You will of course need to have a valid Signer file and an
  26.                 AOCE workstation to try this out.          
  27. */
  28.  
  29.  
  30.  
  31. // ——————————————— needed includes…
  32.  
  33. #include <DigitalSignature.h>    /* AOCE includes */
  34. #include <OCEErrors.h>
  35.  
  36. #include <Memory.h>                /* Mac managers */
  37. #include <Types.h>
  38. #include <Script.h>
  39. #include <Packages.h>
  40. #include <GestaltEqu.h>
  41. #include <console.h>
  42. #include <stdio.h>
  43.  
  44.  
  45. // ——————————————— defines…
  46.  
  47. #define kBufferSize    128
  48. #define kReturn        0x0A
  49.  
  50.  
  51. // ——————————————— declarations…
  52.  
  53. OSErr SaveSignature(SIGSignaturePtr signature, Size signatureSize);
  54. OSErr RetrieveSignature(SIGSignaturePtr *signature, Size *signatureSize);
  55. OSErr GetDataToProcess(Ptr *dataBuffer, Size *dataSize, Boolean *more);
  56.  
  57. void DisplayCertNameAttribute(SIGNameAttributesInfo *name);
  58. void DisplaySignatureInfo(SIGSignerInfo *signerInfo);
  59. void DisplayCertificateInfo(SIGCertInfo *certInfo);
  60.  
  61.  
  62. // ——————————————— globals…
  63.  
  64. SIGSignaturePtr    gSIGSignature = nil;
  65.  
  66.  
  67. // ——————————————— core routines (this is what is in the documentation)…
  68.  
  69. OSErr SignData()
  70. {
  71.     OSErr            error;
  72.     Boolean            moreToSign;
  73.     Size            signatureSize;
  74.     Size            dataSize;
  75.     SIGSignaturePtr    signature    = nil;
  76.     SIGContextPtr    context        = nil;
  77.     Ptr                dataBuffer    = nil;
  78.     
  79.     do {
  80.         // allocate a new context and prepare it for signing
  81.         
  82.         if (error = SIGNewContext(&context))    
  83.             break;
  84.         if (error = SIGSignPrepare(context, (FSSpecPtr)nil, "\p", &signatureSize))
  85.             break;
  86.  
  87.         // retrieve the data to be signed, in our application specific way,
  88.         // and pass it to the toolbox to generate the digest for our signature.
  89.         // NOTE: GetDataToProcess can be the same function for signing and verifying
  90.         
  91.         do {
  92.             if (error = GetDataToProcess(&dataBuffer, &dataSize, &moreToSign))
  93.                 break;
  94.             if (error = SIGProcessData(context, dataBuffer, dataSize))
  95.                 break;
  96.             } while (moreToSign);
  97.         
  98.         if (error)    // if encountered error above, bail all the way out
  99.             break;
  100.  
  101.         // allocate a buffer of the size returned from SIGSignPrepare to hold our 
  102.         // signature then create the signature by passing the buffer to SIGSign
  103.  
  104.         signature = (SIGSignaturePtr)NewPtr(signatureSize);
  105.         if (error = MemError())
  106.             break;
  107.         if (error = SIGSign(context, signature, (SIGStatusProcPtr)nil))
  108.             break;
  109.         
  110.         // save the signature in our application specific way
  111.         
  112.         error = SaveSignature(signature, signatureSize);
  113.         } while (0);
  114.     
  115.     // free the context now (forces user to re-enter their password next
  116.     // time the SIGSignPrepare call is made)
  117.     
  118.     if (context) SIGDisposeContext(context);
  119.  
  120.     if (dataBuffer) DisposPtr(dataBuffer);
  121.     if (signature) DisposPtr((Ptr)signature);
  122.         
  123.     return error;
  124. }
  125.  
  126. OSErr VerifyData()
  127. {
  128.     OSErr            error;
  129.     Boolean            moreToVerify;
  130.     Size            signatureSize;
  131.     Size            dataSize;
  132.     SIGSignaturePtr    signature    = nil;
  133.     SIGContextPtr    context        = nil;
  134.     Ptr                dataBuffer    = nil;
  135.     
  136.     do {
  137.         // get the signature and its size from wherever our application saved it
  138.         
  139.         if (error = RetrieveSignature(&signature, &signatureSize))
  140.             break;
  141.  
  142.         // allocate a new context and prepare it for verifying.  
  143.         
  144.         if (error = SIGNewContext(&context))    
  145.             break;
  146.         if (error = SIGVerifyPrepare(context, signature, signatureSize, (SIGStatusProcPtr)nil))
  147.             break;
  148.  
  149.         // get the data to be verified, in our application specific way,
  150.         // and pass it to the toolbox to generate a digest for our verification
  151.         // NOTE: GetDataToProcess can be the same function for signing and verifying
  152.         
  153.         do {
  154.             if (error = GetDataToProcess(&dataBuffer, &dataSize, &moreToVerify))
  155.                 break;
  156.             if (error = SIGProcessData(context, dataBuffer, dataSize))
  157.                 break;
  158.             } while (moreToVerify);
  159.         
  160.         if (error)    // if encountered error above, bail all the way out
  161.             break;
  162.             
  163.         // now, perform verification
  164.         
  165.         if (error = SIGVerify(context))
  166.             break;
  167.             
  168.         // finally, display the person who signed the data. NOTE: you can call 
  169.         // SIGShowSigner even if a kSIGInvalidCredentialErr was returned from SIGVerify,  
  170.         // we really are being perhaps too strict here (depends on application)
  171.         
  172.         error = SIGShowSigner(context, "\p");
  173.         } while (0);
  174.     
  175.     // free the context
  176.     
  177.     if (context) SIGDisposeContext(context);
  178.  
  179.     if (dataBuffer) DisposPtr(dataBuffer);
  180.     if (signature) DisposPtr((Ptr)signature);
  181.         
  182.     return error;
  183. }
  184.  
  185. OSErr DisplayCertificateSet(SIGContextPtr context)
  186. {
  187.     unsigned short            attrIndex;
  188.     SIGNameAttributesInfo    attrInfo;
  189.     unsigned short            certIndex;
  190.     SIGCertInfo             certInfo;
  191.     SIGSignerInfo            signerInfo;
  192.     OSErr                    error;
  193.     
  194.     do {
  195.         // get and display general signature information first 
  196.         
  197.         if (error = SIGGetSignerInfo(context, &signerInfo))
  198.             break;
  199.         DisplaySignatureInfo(&signerInfo);
  200.             
  201.         // traverse entire certificate set and for each certificate, 
  202.         // display the SIGCertInfo for it then traverse the SIGNameAttributesInfo's
  203.         // for that certificate and display them
  204.         
  205.         for (certIndex = kSIGSignerCertIndex; certIndex < signerInfo.certCount; certIndex++)
  206.             {
  207.             if (error = SIGGetCertInfo(context, certIndex, &certInfo))
  208.                 break;
  209.             DisplayCertificateInfo(&certInfo);
  210.             for (attrIndex = 0; attrIndex < certInfo.certAttributeCount; attrIndex++)
  211.                 {
  212.                 if (error = SIGGetCertNameAttributes(context, certIndex, attrIndex, &attrInfo))
  213.                     break;
  214.                 DisplayCertNameAttribute(&attrInfo);
  215.                 }
  216.             
  217.             // the line below is not in the Inside Mac sample code
  218.             // since it is display dependent!!!
  219.             printf("\n\n** Press any key to continue displaying certificates **");
  220.             getchar();
  221.             printf("\n\n");
  222.             }
  223.         
  224.         // finally, display the root issuers' name attributes. 
  225.         // NOTE: there's no SIGCertInfo for the root, it's always valid etc…
  226.  
  227.         // also, the line below is not in the Inside Mac sample code
  228.         // since it is display dependent!!!
  229.         printf("—————————————————————— ROOT ISSUER ——————————————————————\n");
  230.         
  231.         for (attrIndex = 0; attrIndex < certInfo.issuerAttributeCount; attrIndex++)
  232.             {
  233.             if (error = SIGGetCertIssuerNameAttributes(context, certIndex-1, attrIndex, &attrInfo))
  234.                 break;
  235.             DisplayCertNameAttribute(&attrInfo);
  236.             }
  237.         } while (0);
  238.     
  239.     return error;
  240. }
  241.  
  242.  
  243. // ——————————————— our stub utility routines…
  244.  
  245. OSErr SaveSignature(SIGSignaturePtr signature, Size signatureSize)
  246. {
  247.     OSErr     error    = noErr;
  248.  
  249.     if (gSIGSignature)
  250.         DisposPtr(gSIGSignature);
  251.     
  252.     do {
  253.         gSIGSignature = (SIGSignaturePtr)NewPtr(signatureSize);
  254.         if (error = MemError())
  255.             break;
  256.         BlockMove(signature, gSIGSignature, signatureSize);
  257.         if (error = MemError())
  258.             break;
  259.         } while (0);
  260.         
  261.     return error;
  262. }
  263.  
  264. OSErr RetrieveSignature(SIGSignaturePtr *signature, Size *signatureSize)
  265. {
  266.     // hack test code! We copy the signature here so it doesn't ever get
  267.     // disposed of, makes testing code easier and faster
  268.  
  269.     *signatureSize = GetPtrSize(gSIGSignature);
  270.     *signature = (SIGSignaturePtr)NewPtr(*signatureSize);
  271.     BlockMove(gSIGSignature, *signature, *signatureSize);
  272.  
  273.     return MemError();
  274. }
  275.  
  276. OSErr GetDataToProcess(Ptr *dataBuffer, Size *dataSize, Boolean *more)
  277. {
  278.     OSErr            error    = noErr;
  279.     Ptr                tempPtr    = nil;
  280.     
  281.     do {
  282.         *more = false;
  283.         if (*dataBuffer == nil)
  284.             {
  285.             *dataSize = kBufferSize;
  286.             *dataBuffer = tempPtr = NewPtr(*dataSize);
  287.             if (error = MemError())
  288.                 break;
  289.             }
  290.         else
  291.             tempPtr = *dataBuffer;
  292.         memset(tempPtr, 1, *dataSize);
  293.         } while (0);
  294.     
  295.     return error;
  296. }
  297.  
  298. void DisplayCertNameAttribute(SIGNameAttributesInfo *name)
  299. {
  300.     p2cstr((StringPtr)&name->attribute);
  301.     printf("%d      %d    %d  %s\n", name->onNewLevel, name->attributeScript, name->attributeType, name->attribute);
  302. }
  303.  
  304. void DisplaySignatureInfo(SIGSignerInfo *signerInfo)
  305. {
  306.     Str255    time;
  307.     Str255    date;
  308.     
  309.     printf("—————————————————————— SIGNER INFO ——————————————————————\n");
  310.  
  311.     IUDateString(signerInfo->signingTime, abbrevDate, date);            // sign date
  312.     p2cstr((StringPtr)&date);
  313.     IUTimeString(signerInfo->signingTime, true, time);                    // sign time
  314.     p2cstr((StringPtr)&time);
  315.     printf("signing time:         %s %s\n", &date, &time);
  316.  
  317.     printf("number of certs:      %d\n", signerInfo->certCount);        // num certs
  318.  
  319.     IUDateString(signerInfo->certSetStatusTime, abbrevDate, date);        // sign date
  320.     p2cstr((StringPtr)&date);
  321.     IUTimeString(signerInfo->certSetStatusTime, true, time);            // sign time
  322.     p2cstr((StringPtr)&time);
  323.     printf("cert set status time: %s %s\n", &date, &time);
  324.  
  325.     switch (signerInfo->signatureStatus) {                                // status
  326.         case kSIGValid: 
  327.             printf("cert set status:      valid\n"); break;
  328.         case kSIGPending: 
  329.             printf("cert set status:      pending\n"); break;
  330.         case kSIGExpired: 
  331.             printf("cert set status:      expired\n"); break;
  332.         case kSIGInvalid: 
  333.             printf("cert set status:      envalid\n"); break;
  334.         default:
  335.             printf("cert set status:      UNKOWN!\n");
  336.         }
  337.  
  338.     printf("—————————————————————————————————————————————————————————\n");
  339. }
  340.  
  341. void DisplayCertificateInfo(SIGCertInfo *certInfo)
  342. {
  343.     Str255    date;
  344.  
  345.     printf("——————————————————————— CERT INFO ———————————————————————\n");
  346.  
  347.     IUDateString(certInfo->startDate, abbrevDate, date);            // start validity date
  348.     p2cstr((StringPtr)&date);
  349.     printf("start validity date:    %s\n", &date);
  350.  
  351.     IUDateString(certInfo->endDate, abbrevDate, date);                // end validity date
  352.     p2cstr((StringPtr)&date);
  353.     printf("end validity date:      %s\n", &date);
  354.  
  355.     switch (certInfo->certStatus) 
  356.         {                
  357.         case kSIGValid: 
  358.             printf("cert status:            valid\n"); break;
  359.         case kSIGPending: 
  360.             printf("cert status:            pending\n"); break;
  361.         case kSIGExpired: 
  362.             printf("cert status:            expired\n"); break;
  363.         default:
  364.             printf("cert status:            UNKOWN!\n");
  365.         } 
  366.         
  367.     printf("cert attribute count:   %d\n", certInfo->certAttributeCount);
  368.     printf("issuer attribute count: %d\n", certInfo->issuerAttributeCount);
  369.     p2cstr((StringPtr)&certInfo->serialNumber);
  370.     printf("serial number:          %s\n", &certInfo->serialNumber);
  371.     printf("—————————————————————————————————————————————————————————\n");
  372. }
  373.  
  374.  
  375.  
  376. // ——————————————— routines to get us up and running only (not necessarily exemplary)…
  377.  
  378. void ClearConsole()
  379. {
  380.     cgotoxy(1,1, stdout);
  381.     ccleos(stdout);
  382. }
  383.  
  384. OSErr Prep2DisplayCertificateSet()
  385. {
  386.     OSErr            error;
  387.     Boolean            more;
  388.     Size            signatureSize;
  389.     Size            dataSize;
  390.     SIGSignaturePtr    signature    = nil;
  391.     SIGContextPtr    context        = nil;
  392.     Ptr                dataBuffer    = nil;
  393.     
  394.     do {
  395.         // NOTE: For our sample purposes, we are doing another "fresh"
  396.         // verify here so the functions can remain autonomous. This is by
  397.         // no means an efficient little tool or anything. There must have
  398.         // been a signature created however to get here!
  399.         
  400.         if (error = RetrieveSignature(&signature, &signatureSize))
  401.             break;
  402.         if (error = SIGNewContext(&context))    
  403.             break;
  404.         if (error = SIGVerifyPrepare(context, signature, signatureSize, (SIGStatusProcPtr)nil))
  405.             break;
  406.         do {
  407.             if (error = GetDataToProcess(&dataBuffer, &dataSize, &more))
  408.                 break;
  409.             if (error = SIGProcessData(context, dataBuffer, dataSize))
  410.                 break;
  411.             } while (more);
  412.         if (error)    // if encountered error above, bail all the way out
  413.             break;
  414.         if (error = SIGVerify(context))
  415.             break;
  416.         
  417.         ClearConsole();
  418.  
  419.         // now instead of calling show signer, we will display the certificate
  420.         // set ourselves to the user (not a great interface)…
  421.         
  422.         error = DisplayCertificateSet(context);
  423.         } while (0);
  424.  
  425.     if (context) SIGDisposeContext(context);
  426.  
  427.     if (dataBuffer) DisposPtr(dataBuffer);
  428.     if (signature) DisposPtr((Ptr)signature);
  429.         
  430.     return error;
  431. }
  432.  
  433. char * MapErrorCode(error)
  434. {
  435.     switch (error)
  436.         {
  437.         case kSIGOperationIncompatibleErr:
  438.             return "context in user for another type of operation";
  439.         case kSIGUserCanceled:
  440.             return "user canceled operation";
  441.         case kSIGVerifyFailedErr:
  442.             return "verification failed";
  443.         case kSIGInvalidCredentialErr:
  444.             return "verified OK but certificate is invaid (expired or pending)";
  445.         case kSIGIndexErr:
  446.             return "index given for attribute or certificate is invalid";
  447.         case kSIGSignerErr:
  448.             return "problem with Signer";
  449.         case kSIGPasswordErr:
  450.             return "incorrect password";
  451.         case kSIGInternalsErr:
  452.             return "internal error";
  453.         case kSIGContextPrepareErr:
  454.             return "context already prepared";
  455.         case kSIGNoDigestErr:
  456.             return "no digest in the signature";
  457.         case kSIGConversionErr:
  458.             return "unable to decode an attribute";
  459.         case kSIGSignerNotValidErr:
  460.             return "Signer has expired or is pending, can't be used";
  461.         case kSIGNoSignature:
  462.             return "standard signature not found";
  463.         default:
  464.             return "Operating System Error";
  465.         }
  466. }
  467.  
  468. void ExecuteSampleCode()
  469. {
  470.     char*    process;
  471.     OSErr    error      = noErr;
  472.     
  473.     do {
  474.         ClearConsole();
  475.         process = "SignData";
  476.         printf("Try out %s function…\n", process);
  477.         if (error = SignData())
  478.             break;
  479.         ClearConsole();
  480.         process = "VerifyData";
  481.         printf("Try out %s function…\n", process);
  482.         if (error = VerifyData())
  483.             break;
  484.         ClearConsole();
  485.         process = "DisplayCertificateSet";
  486.         printf("Try out %s function…\n", process);
  487.         if (error = Prep2DisplayCertificateSet())
  488.             break;
  489.         printf("\n\n** Press <return> to exit **");
  490.         } while (0);
  491.     
  492.     if (error)
  493.         printf("### %s error %d %s", process, error, MapErrorCode(error));
  494. }
  495.  
  496. void PrepareConsole()
  497. {
  498.     char c;
  499.  
  500.     console_options.title = "\pDigital Signature Sample Code";
  501.     console_options.top = 40;
  502.     console_options.left = 3;
  503.     console_options.nrows = 27;
  504.     console_options.ncols = 83;
  505.     cshow(stdout);
  506.     csetmode(C_NOECHO /*C_CBREAK*/, stdout);
  507.  
  508.     ClearConsole();
  509.     printf("This little application simply executes the sample code\n");
  510.     printf("found in the Digital Signature chapter of Inside Mac\n");
  511.     printf("© 1990-1993 Apple Computer, Inc.\n\n");
  512.  
  513.     printf("Press return key to run the Inside Mac sample code,\n");
  514.     printf("any other key will cancel:");
  515.     c = getchar();
  516.     
  517.     if (c != kReturn)
  518.         ExitToShell();
  519. }
  520.  
  521. void main ()
  522. {
  523.     long ignore;
  524.     
  525.     PrepareConsole();
  526.         
  527.     InitGraf(&thePort);
  528.     InitFonts();
  529.     InitWindows();
  530.     InitDialogs(nil);
  531.     InitCursor();
  532.     
  533.     if (Gestalt(gestaltDigitalSignatureVersion, &ignore) == noErr)
  534.         {
  535.         ExecuteSampleCode();
  536.         if (gSIGSignature)
  537.             DisposPtr((Ptr)gSIGSignature); 
  538.         }
  539.     else
  540.         printf("\n\n### Digital Signature toolbox not available!");
  541. }